// src/pages/test/childTest/index.tsx - React中实现类似Vue Slot功能详解页面
import React, { useState } from 'react';
import { Card, Button, Space, Typography, Divider, Input } from 'antd';

const { Title, Paragraph } = Typography;

/**
 * 1. 默认插槽示例 - 类似于Vue中的<slot />
 * 在React中通过props.children实现
 */
interface DefaultSlotCardProps {
  title: string;
  children: React.ReactNode;
}

const DefaultSlotCard: React.FC<DefaultSlotCardProps> = ({ title, children }) => {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '4px', padding: '16px', margin: '16px 0' }}>
      <h3>{title}</h3>
      <div>{children}</div>
    </div>
  );
};

/**
 * 2. 具名插槽示例 - 类似于Vue中的<slot name="header" />
 * 在React中通过传递多个props实现
 */
interface NamedSlotsCardProps {
  header: React.ReactNode;
  content: React.ReactNode;
  footer: React.ReactNode;
}

const NamedSlotsCard: React.FC<NamedSlotsCardProps> = ({ header, content, footer }) => {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '4px', padding: '16px', margin: '16px 0' }}>
      <div style={{ borderBottom: '1px solid #eee', paddingBottom: '8px' }}>{header}</div>
      <div style={{ padding: '16px 0' }}>{content}</div>
      <div style={{ borderTop: '1px solid #eee', paddingTop: '8px' }}>{footer}</div>
    </div>
  );
};

/**
 * 3. 作用域插槽示例 - 类似于Vue中的<slot :data="data" />
 * 在React中通过传递渲染函数实现
 */
interface ScopedSlotListProps {
  items: string[];
  renderItem: (item: string, index: number) => React.ReactNode;
}

const ScopedSlotList: React.FC<ScopedSlotListProps> = ({ items, renderItem }) => {
  return (
    <div>
      <ul>
        {items.map((item, index) => (
          <li key={index} style={{ listStyle: 'none', padding: '8px 0' }}>
            {renderItem(item, index)}
          </li>
        ))}
      </ul>
    </div>
  );
};

/**
 * 4. 复杂插槽示例 - 结合多种插槽类型
 */
interface ComplexCardProps {
  header: React.ReactNode;
  footer: React.ReactNode;
  renderItem: (item: { id: number; name: string }) => React.ReactNode;
  items: { id: number; name: string }[];
}

const ComplexCard: React.FC<ComplexCardProps> = ({ header, footer, renderItem, items }) => {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '4px', padding: '16px', margin: '16px 0' }}>
      <div style={{ borderBottom: '1px solid #eee', paddingBottom: '8px' }}>{header}</div>
      <div style={{ padding: '16px 0' }}>
        {items.map(item => (
          <div key={item.id} style={{ padding: '8px', borderBottom: '1px solid #f5f5f5' }}>
            {renderItem(item)}
          </div>
        ))}
      </div>
      <div style={{ borderTop: '1px solid #eee', paddingTop: '8px' }}>{footer}</div>
    </div>
  );
};

/**
 * 5. 使用Context API实现插槽 - 适用于复杂嵌套场景
 */
const CardContext = React.createContext<{
  title?: string;
  onAction?: () => void;
}>({});

interface ContextSlotCardProps {
  title: string;
  onAction: () => void;
  children: React.ReactNode;
}

const ContextSlotCard: React.FC<ContextSlotCardProps> = ({ title, onAction, children }) => {
  return (
    <CardContext.Provider value={{ title, onAction }}>
      <div style={{ border: '1px solid #ddd', borderRadius: '4px', padding: '16px', margin: '16px 0' }}>
        {children}
      </div>
    </CardContext.Provider>
  );
};

const CardHeader: React.FC = () => {
  const context = React.useContext(CardContext);
  return (
    <div style={{ borderBottom: '1px solid #eee', paddingBottom: '8px' }}>
      <h3>{context.title}</h3>
    </div>
  );
};

const CardFooter: React.FC = () => {
  const context = React.useContext(CardContext);
  return (
    <div style={{ borderTop: '1px solid #eee', paddingTop: '8px' }}>
      <Button type="primary" onClick={context.onAction}>执行操作</Button>
    </div>
  );
};

const ChildTestPage: React.FC = () => {
  const [inputValue, setInputValue] = useState('');

  return (
    <Card title="React中实现类似Vue Slot功能详解" style={{ minHeight: '100%' }}>
      <Typography>
        <Title level={2}>React中的插槽(Slot)机制</Title>
        <Paragraph>
          在Vue中，插槽(Slot)是一种非常强大的内容分发机制，允许我们在组件中定义可替换的内容。
          虽然React没有内置的Slot概念，但我们可以使用多种方式实现类似的功能。
        </Paragraph>
      </Typography>

      <Divider />
      
      {/* 1. 默认插槽示例 */}
      <Title level={3}>1. 默认插槽 - props.children</Title>
      <Paragraph>
        在React中，最简单的插槽实现方式是使用props.children，这类似于Vue中的默认插槽。
      </Paragraph>
      
      <DefaultSlotCard title="默认插槽示例">
        <p>这是插入到默认插槽中的内容</p>
        <Button type="primary">按钮</Button>
      </DefaultSlotCard>
      
      <Paragraph>
        <pre>
          {`// 父组件
<DefaultSlotCard title="默认插槽示例">
  <p>这是插入到默认插槽中的内容</p>
  <Button type="primary">按钮</Button>
</DefaultSlotCard>

// DefaultSlotCard组件
interface DefaultSlotCardProps {
  title: string;
  children: React.ReactNode;
}

const DefaultSlotCard: React.FC<DefaultSlotCardProps> = ({ title, children }) => {
  return (
    <div>
      <h3>{title}</h3>
      <div>{children}</div>
    </div>
  );
};`}
        </pre>
      </Paragraph>
      
      <Divider />
      
      {/* 2. 具名插槽示例 */}
      <Title level={3}>2. 具名插槽 - 多个props</Title>
      <Paragraph>
        在Vue中，我们可以通过&lt;slot name="header"&gt;定义具名插槽。
        在React中，我们可以通过传递多个props来实现类似功能。
      </Paragraph>
      
      <NamedSlotsCard 
        header={<h3>这是头部内容</h3>}
        content={
          <div>
            <p>这是主要内容区域</p>
            <Input placeholder="请输入内容" />
          </div>
        }
        footer={
          <Space>
            <Button>取消</Button>
            <Button type="primary">确定</Button>
          </Space>
        }
      />
      
      <Paragraph>
        <pre>
          {`// 父组件
<NamedSlotsCard 
  header={<h3>这是头部内容</h3>}
  content={<p>这是主要内容区域</p>}
  footer={<Button>确定</Button>}
/>

// NamedSlotsCard组件
interface NamedSlotsCardProps {
  header: React.ReactNode;
  content: React.ReactNode;
  footer: React.ReactNode;
}

const NamedSlotsCard: React.FC<NamedSlotsCardProps> = ({ header, content, footer }) => {
  return (
    <div>
      <div>{header}</div>
      <div>{content}</div>
      <div>{footer}</div>
    </div>
  );
};`}
        </pre>
      </Paragraph>
      
      <Divider />
      
      {/* 3. 作用域插槽示例 */}
      <Title level={3}>3. 作用域插槽 - 渲染函数</Title>
      <Paragraph>
        在Vue中，作用域插槽允许子组件向父组件传递数据。
        在React中，我们可以通过传递渲染函数来实现类似功能。
      </Paragraph>
      
      <ScopedSlotList 
        items={['苹果', '香蕉', '橙子']}
        renderItem={(item, index) => (
          <Space>
            <span>{index + 1}. {item}</span>
            <Button size="small" onClick={() => alert(`你选择了${item}`)}>选择</Button>
          </Space>
        )}
      />
      
      <Paragraph>
        <pre>
          {`// 父组件
<ScopedSlotList 
  items={['苹果', '香蕉', '橙子']}
  renderItem={(item, index) => (
    <Space>
      <span>{index + 1}. {item}</span>
      <Button onClick={() => alert(\`你选择了\${item}\`)}>选择</Button>
    </Space>
  )}
/>

// ScopedSlotList组件
interface ScopedSlotListProps {
  items: string[];
  renderItem: (item: string, index: number) => React.ReactNode;
}

const ScopedSlotList: React.FC<ScopedSlotListProps> = ({ items, renderItem }) => {
  return (
    <div>
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            {renderItem(item, index)}
          </li>
        ))}
      </ul>
    </div>
  );
};`}
        </pre>
      </Paragraph>
      
      <Divider />
      
      {/* 4. 复杂插槽示例 */}
      <Title level={3}>4. 复杂插槽示例</Title>
      <Paragraph>
        结合多种插槽类型，实现更复杂的组件。
      </Paragraph>
      
      <ComplexCard
        header={<h2>用户列表</h2>}
        footer={<div>总共 {3} 个用户</div>}
        items={[
          { id: 1, name: '张三' },
          { id: 2, name: '李四' },
          { id: 3, name: '王五' }
        ]}
        renderItem={(item) => (
          <Space>
            <span>{item.name}</span>
            <Button size="small" onClick={() => alert(`编辑用户: ${item.name}`)}>编辑</Button>
          </Space>
        )}
      />
      
      <Paragraph>
        <pre>
          {`// 父组件
<ComplexCard
  header={<h2>用户列表</h2>}
  footer={<div>总共 {users.length} 个用户</div>}
  items={users}
  renderItem={(item) => (
    <Space>
      <span>{item.name}</span>
      <Button onClick={() => alert(\`编辑用户: \${item.name}\`)}>编辑</Button>
    </Space>
  )}
/>`}
        </pre>
      </Paragraph>
      
      <Divider />
      
      {/* 5. Context API插槽示例 */}
      <Title level={3}>5. 使用Context API实现插槽</Title>
      <Paragraph>
        对于复杂的嵌套场景，可以使用Context API来实现插槽功能。
      </Paragraph>
      
      <ContextSlotCard 
        title="Context插槽示例"
        onAction={() => alert('执行了操作')}
      >
        <CardHeader />
        <div style={{ padding: '16px 0' }}>
          <Input 
            placeholder="请输入内容" 
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
          />
          <p style={{ marginTop: '8px' }}>输入的内容: {inputValue}</p>
        </div>
        <CardFooter />
      </ContextSlotCard>
      
      <Paragraph>
        <pre>
          {`// 创建Context
const CardContext = React.createContext({});

// 父组件
<ContextSlotCard title="Context插槽示例" onAction={() => alert('执行了操作')}>
  <CardHeader />
  <div>中间内容</div>
  <CardFooter />
</ContextSlotCard>

// ContextSlotCard组件
const ContextSlotCard: React.FC<ContextSlotCardProps> = ({ title, onAction, children }) => {
  return (
    <CardContext.Provider value={{ title, onAction }}>
      <div>{children}</div>
    </CardContext.Provider>
  );
};

// CardHeader组件
const CardHeader: React.FC = () => {
  const context = React.useContext(CardContext);
  return <h3>{context.title}</h3>;
};`}
        </pre>
      </Paragraph>
      
      <Divider />
      
      <Title level={3}>使用场景</Title>
      <Paragraph>
        <ul>
          <li>
            <strong>UI组件库开发：</strong>
            开发可复用的卡片、模态框、表格等组件时，需要允许用户自定义内容
          </li>
          <li>
            <strong>布局组件：</strong>
            创建页面布局组件，允许在不同页面中插入不同的内容
          </li>
          <li>
            <strong>列表组件：</strong>
            创建通用的列表组件，允许父组件自定义列表项的渲染方式
          </li>
          <li>
            <strong>表单组件：</strong>
            创建表单容器组件，允许插入不同的表单项
          </li>
          <li>
            <strong>复杂嵌套组件：</strong>
            当组件层级较深，需要在深层组件中传递内容时
          </li>
        </ul>
      </Paragraph>
      
      <Title level={3}>注意事项</Title>
      <Paragraph>
        <ul>
          <li>
            <strong>性能考虑：</strong>
            使用props传递ReactNode时要注意避免不必要的重新渲染
          </li>
          <li>
            <strong>类型安全：</strong>
            在TypeScript中要为插槽内容定义合适的类型
          </li>
          <li>
            <strong>默认值：</strong>
            可以为插槽内容提供默认值，提高组件的易用性
          </li>
          <li>
            <strong>文档说明：</strong>
            使用插槽的组件需要清楚地说明每个插槽的用途和使用方式
          </li>
        </ul>
      </Paragraph>
    </Card>
  );
};

export default ChildTestPage;